#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import defclass as dc
import functions as func

# pretreatment
# delete the information lines and only save data to another file
fi = open("../dataset/seismic-bumps.arff", "r")
fo = open("./data.txt", "w")
while True:
    buffer = fi.readline()
    if not buffer:
        break
    if not('%' in buffer or '@' in buffer or len(buffer) <= 1):
        fo.write(buffer)
fi.close()
fo.close()

# read data set, stored in variable: dataset
fdata = open("./data.txt", "r")
dataset = []
while True:
    buffer = fdata.readline()
    if not buffer:
        break
    # template variables
    term_tem = buffer.split(sep=',')
    seismic_t = term_tem[0]
    seismo_t = term_tem[1]
    shift_t = term_tem[2]
    genergy_t = float(term_tem[3])
    gpuls_t = float(term_tem[4])
    gdenergy_t = float(term_tem[5])
    gdpuls_t = float(term_tem[6])
    ghazard_t = term_tem[7]
    nbumps_t = [float(term_tem[i]) for i in range(8, 16)]
    energy_t = float(term_tem[16])
    maxenergy_t = float(term_tem[17])
    tag_t = float(term_tem[18])
    # template term
    term_c = dc.term(seismic_t, seismo_t, shift_t, genergy_t, gpuls_t,
                     gdenergy_t, gdpuls_t, ghazard_t, nbumps_t, energy_t,
                     maxenergy_t, tag_t)
    # add to dataset
    dataset.append(term_c)
fdata.close()


def train():
    global weight_xy
    global weight_yo
    j = 0
    while j < 100:  # avoid endless cycle
        j += 1
        err_total = 0.0
        for i in range(0, Devide):
            # calculate output
            flg = func.judge(trainset[i], x, y, o, weight_xy, weight_yo,
                             XNUM, YNUM)
            # calculate error
            ok = float(flg)
            dk = trainset[i].tag
            error = (dk - ok)**2.0 +\
                lam*(np.sum(weight_xy**2) + np.sum(weight_yo**2))
            if error > err_total:  # remember largest error
                err_total = error
            delta_o = (dk - ok)*(1.0 - ok)*ok
            delta_y = delta_o*np.transpose(weight_yo)*(1.0-y)*y
            weight_yo = weight_yo + yita*delta_o*np.transpose(y)
            weight_xy = weight_xy*np.ones([XNUM, YNUM])\
                + yita*np.dot(np.transpose(x), delta_y)
        if err_total < 5.0:
            break


def statistic():
    for i in range(0, len(testset)):
        flg = func.judge(testset[i], x, y, o, weight_xy, weight_yo, XNUM, YNUM)
        ok = float(flg)
        dk = testset[i].tag
        func.count(ok, dk, testmat)
    func.stat(testmat, result)


# prepare data
fresult = open("./result.txt", "w")
lst = [10*i for i in range(1, 51)]
r = []
testmat = {'TP': 0, 'TN': 0, 'FP': 0, 'FN': 0}
result = {}
for tt in lst:
    Devide = tt
    XNUM = 18
    YNUM = 20
    yita = 1.0
    lam = 0.005
    trainset = dataset[:Devide]
    testset = dataset[501:]
    weight_xy = np.random.ranf([XNUM, YNUM])
    weight_yo = np.random.ranf([YNUM, 1])
    x = np.ones([1, XNUM])
    y = np.ones([1, YNUM])
    o = np.ones([1, 1])
    # process
    # train
    train()
    # check training results
    statistic()
    # output results
    r.append(result['acc'])
    fresult.write("{}\t{}\n".format(Devide, result))
fresult.close()
plt.figure(1)
plt.plot(lst, r, linewidth=2.0)
plt.xlabel("Training set's size")
plt.ylabel("Accuacy")
plt.savefig("./result.png", format='png')
plt.show()
